﻿#define  _CRT_SECURE_NO_WARNINGS   1
#include <iostream>
#include <string>
#include<vector>
using namespace std;

//继承就是一种复用的体现
//父类/基类  子类/派生类

//class Person
//{
//public:
////	// 进⼊校园/图书馆/实验室刷⼆维码等⾝份认证
//	void identity()
//	{
//		//cout << "void identity()" << _name << endl;
//		cout << &_age << endl;
//	}
//protected:
//	string _name = "张三"; // 姓名
//	string _address; // 地址
//	string _tel; // 电话
//	int _age = 18; // 年龄
//};
//
//class Student : public Person
//{
//public:
//	// 学习
//	void study()
//	{
//		// ...
//		cout << &_age << endl;
//	}
//	protected:
//		int _stuid; // 学号
//};
//class Teacher : public Person
//{
//public:
//	// 授课
//	void teaching()
//	{
//		//...
//		cout << &_age << endl;
//
//	}
//protected:
//	string title; // 职称
//};

//一般采用protected成员和public继承方式
//protected和private的区别，在类里面没有区别，在继承就会有区别
//protected修饰，派生类可以访问，类外不可访问
//private修饰，派生类，类外都不可访问
//class Person
//{
//public:
//	void Print()
//	{
//		cout << _name << endl;
//		cout << _age << endl;
//	}
//protected:
//	string _name="张三"; // 姓名
//private:
//	int _age=20; // 年龄
//};
////class Student : protected Person
////class Student : private Person
//class Student : public Person
//{
//public:
//	void fun()
//	{
//		Print();
//	}
//protected:
//	int _stunum; // 学号
//};
//
//namespace wwp
//{
	//类模板的继承
//	template<class T>
//	class stack:public vector<T>
//	{
//	public: 
//		void push(const T& x)
//		{
//			vector<T>::push_back(x);	//类模板必须就这样的写法
//		}
//		void pop()
//		{
//			vector<T>::pop_back();
//		}
//	private:
//		vector<T> _con;
//	};
//}

//派生类在实例化对象的时候，也要为基类成员变量分配空间
//int main()
//{
//	//Person p1;
//	//Student s1;
//	//Teacher t1;
//	//p1.identity();
//	//s1.study();
//	//t1.teaching();
//	//s1.identity();
//	/*s1.fun();
//	s1.Print();*/
//	//wwp::stack<int> s1;
//	return 0;
//}

//基类和派生类之间的关系
//class Person
//{
//protected:
//	string _name; // 姓名
//	string _sex; // 性别
//	int _age; // 年龄
//};
//class Student : public Person
//{
//public:
//	int _No; // 学号
//};
//int main()
//{
//	//基类直指向属于自己的部分
//	Student sobj;
//	// 1.派⽣类对象可以赋值给基类的指针/引⽤
//	Person* pp = &sobj;
//	Person& rp = sobj;
//	// 派⽣类对象可以赋值给基类的对象是通过调⽤后⾯会讲解的基类的拷⻉构造完成的
//	Person pobj = sobj;
//	//2.基类对象不能赋值给派⽣类对象，这⾥会编译报错
//	//sobj = pobj;
//	return 0;
//}

// Student的_num和Person的_num构成隐藏关系，可以看出这样代码虽然能跑，但是⾮常容易混淆
//class Person
//{
//protected:
//	string _name = "⼩李⼦"; // 姓名
//	int _num = 111; // ⾝份证号
//};
//class Student : public Person
//{
//public:
//	void Print()
//	{
//		//cout << " 姓名:" << _name << endl;
//		cout << " ⾝份证号:" << Person::_num << endl;
//		cout << " 学号:" << _num << endl;
//	}
//protected:
//	int _num = 999; // 学号
//};
////派生类中的成员变量和成员函数名字和基类中的相同的时候，就会自动屏蔽基类中的，这叫做隐藏
////函数重载的形成必须在同一个作用域中
//int main()
//{
//	Student s1;
//	s1.Print();
//	return 0;
//};

//class A
//{
//public:
//	void fun()
//	{
//		cout << "func()" << endl;
//	}
//};
//class B : public A
//{
//public:
//	void fun(int i)
//	{
//		cout << "func(int i)" << i << endl;
//	}
//};
//int main()
//{
//	B b;
//	b.fun(10);
//	//b.fun();
//	return 0;
//};

//把基类中的成员看成一个整体的自定义类型
//派⽣类的构造函数必须调⽤基类的构造函数初始化基类的那⼀部分成员。如果基类没有默认的构造
//函数，则必须在派⽣类构造函数的初始化列表阶段显⽰调⽤。

//派生类的4个默认函数
//派生类的基类成员不显示写构造函数，就会调用基类的构造函数	Person(s)
//派生类的基类成员拷贝构造函数必须要调用基类自己的拷贝构造函数 Person(s)
//派生类的赋值运算符重载，也要调用基类的赋值运算符重载 Person::operator=()
//析构不需要显示写基类的，它会自动调用自己的析构
//先构造基类部分再构造派生类，先析构派生类，再析构基类